
package com.tools.cleanmaster.utils;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextUtils;

import com.tools.cleanmaster.CleanApplication;
import com.tools.cleanmaster.appinfo.AppInfoCompat;
import com.tools.cleanmaster.appinfo.AppInfoSnapshot;
import com.tools.cleanmaster.appinfo.AppManager;
import com.tools.cleanmaster.appinfo.AppManagerCompat;
import com.tools.cleanmaster.appinfo.PackageCompat;

import java.util.List;

/**
 * TODO move the PackageUtils from DX Optimizer into this library and remove
 * this one
 */
public class PackageUtils {
    private static int mDefaultInstallLocation = PackageCompat.getInstallLocation();

    public static class PkgInfo {
        public String pkgName;

        /**
         * May be null.
         */
        public String label;

        /**
         * May be null.
         */
        public Drawable icon;

        /**
         * May be null.
         */
        public String versionName;

        /**
         * May be 0.
         */
        public int versionCode;
    }

    /**
     * @return null may be returned if the package not found
     */
    public static PackageInfo getPkgInfo(Context context, String pkgName) {
        PackageInfo pkgInfo = null;
        AppInfoSnapshot info = AppManager.getInstance(context).getAppInfo(pkgName);
        if (info != null) {
            pkgInfo = new PackageInfo();
            pkgInfo.versionName = info.getVersionName();
            pkgInfo.versionCode = info.getVersionCode();
        }
        return pkgInfo;
    }

    public static boolean moveToSDAdvice(PackageInfo pkgInfo) {
        if (pkgInfo == null)
            return false;
        int installLocation = PackageCompat.packageInfo_installLocation(pkgInfo);
        if (installLocation == PackageCompat.INSTALL_LOCATION_PREFER_EXTERNAL
                || installLocation == PackageCompat.INSTALL_LOCATION_AUTO) {
            return true;
        } else if (installLocation == PackageCompat.INSTALL_LOCATION_UNSPECIFIED) {
            return mDefaultInstallLocation == PackageCompat.APP_INSTALL_EXTERNAL;
        }
        return false;
    }

    public static void killPackage(Context context, String pkgName) {
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        killBackgroundProcesses(am, pkgName);
    }


    /**
     * 没有杀进程的权限，可能会导致，山进程不成功
     *
     * @param am
     * @param pkgName
     */
    @SuppressLint("MissingPermission")
    private static void killBackgroundProcesses(ActivityManager am, String pkgName) {
        if (am != null && !TextUtils.isEmpty(pkgName)) {
            try {
                am.killBackgroundProcesses(pkgName);
            } catch (Throwable throwable) {
                // LG 品牌，在底层处理的时候，真奔溃
            }
        }
    }

    public static PkgInfo getArchievePkgInfo(Context context, String apkFilepath) {
        PackageManager pm = context.getPackageManager();
        PackageInfo pkgInfo = null;
        try {
            pkgInfo = pm.getPackageArchiveInfo(apkFilepath, 0);
        } catch (Exception e) {
            // should be something wrong with parse
            e.printStackTrace();
        }
        if (pkgInfo == null) {
            return null;
        }

        // Workaround for http://code.google.com/p/android/issues/detail?id=9151
        ApplicationInfo appInfo = pkgInfo.applicationInfo;
        if (Build.VERSION.SDK_INT >= 8) {
            appInfo.sourceDir = apkFilepath;
            appInfo.publicSourceDir = apkFilepath;
        }

        PkgInfo info = new PkgInfo();
        info.pkgName = pkgInfo.packageName;
        info.versionName = pkgInfo.versionName;
        info.versionCode = pkgInfo.versionCode;

        CharSequence label = pm.getApplicationLabel(appInfo);
        if (label != null) {
            info.label = StringUtils.trimAppName(label.toString());
        } else {
            info.label = null;
        }
        info.icon = pm.getApplicationIcon(appInfo);
        return info;
    }

    public static Drawable getAppIcon(Context context, String apkFilepath) {
        PackageManager pm = context.getPackageManager();
        PackageInfo pkgInfo = null;
        try {
            pkgInfo = pm.getPackageArchiveInfo(apkFilepath, 0);
        } catch (Exception e) {
            // should be something wrong with parse
            e.printStackTrace();
        }
        if (pkgInfo == null) {
            return null;
        }

        // Workaround for http://code.google.com/p/android/issues/detail?id=9151
        ApplicationInfo appInfo = pkgInfo.applicationInfo;
        if (Build.VERSION.SDK_INT >= 8) {
            appInfo.sourceDir = apkFilepath;
            appInfo.publicSourceDir = apkFilepath;
        }

        return pm.getApplicationIcon(appInfo);
    }

    public static int getVersionCode(Context context, String pkgName, int defValue) {
        PackageInfo pkgInfo = getPkgInfo(context, pkgName);
        if (pkgInfo != null) {
            defValue = pkgInfo.versionCode;
        }
        return defValue;
    }

    /**
     * @return null may be returned if the package not found
     */
    public static String getPkgLabel(String pkgName) {
        AppInfoSnapshot info = AppManager.getInstance(CleanApplication.getInstance()).getAppInfo(pkgName);
        return info.getLabel();
    }

    public static String getVersionName(Context cxt, String pkgName) {
        PackageInfo pkgInfo = getPkgInfo(cxt, pkgName);
        return pkgInfo != null ? pkgInfo.versionName : null;
    }

    public static boolean isPkgInstalled(Context context, String pkgName) {
        PackageManager pm = context.getPackageManager();
        boolean installed = false;
        try {
            pm.getPackageInfo(pkgName, 0);
            installed = true;
        } catch (NameNotFoundException e) {
            // ignore the exception
        }
        return installed;
    }

    /**
     * 获取所有安装应用名称
     *
     * @param context
     * @return
     */
    public static String[] allPackageNames(Context context) {
        PackageManager packageManager = context.getApplicationContext().getPackageManager();
        List<PackageInfo> installedApps = packageManager.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
        String[] allPackageNameStrings = new String[installedApps.size()];
        for (int i = 0, len = allPackageNameStrings.length; i < len; i++) {
            allPackageNameStrings[i] = installedApps.get(i).applicationInfo.loadLabel(packageManager).toString();
        }
        return allPackageNameStrings;
    }

    public static boolean isIntentCanBeHandled(Context ctx, Intent intent) {
        if (intent == null || ctx == null) {
            return false;
        }
        PackageManager packageManager = ctx.getPackageManager();
        List<ResolveInfo> list = packageManager.queryIntentActivities(intent,
                PackageManager.GET_ACTIVITIES);
        return list != null && list.size() > 0;
    }

    public static boolean isAppInstalled(Context context, String pkgName) {
        return isPkgInstalled(context, pkgName);
    }

    /**
     * 判断指定action是否存在
     *
     * @param cxt
     * @param action
     * @return
     */
    public static boolean isAction(Context cxt, String action) {
        PackageManager packageManager = cxt.getPackageManager();
        Intent intent = new Intent(action);
        List resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.GET_INTENT_FILTERS);
        return resolveInfo != null && !resolveInfo.isEmpty();
    }

    public static boolean isSystemApp(Context context, String pkgName) {
        try {
            AppInfoCompat info = AppManagerCompat.getAppInfo(pkgName);
            return info.isSystem();
        } catch (NameNotFoundException e) {
            // ignore the exception
        }
        return true; // default to system apps
    }
}
